// Initialize checkboxes for seconds, minutes, etc.
function initializeCheckboxes(containerId, max, prefix = "", start = 0) {
    const container = document.getElementById(containerId);
    for (let i = start; i <= max; i++) {
        const checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.value = i;
        checkbox.id = `${containerId}-${i}`;
        const label = document.createElement("label");
        label.htmlFor = `${containerId}-${i}`;
        label.innerText = prefix ? `${prefix} ${i}` : i;
        container.appendChild(checkbox);
        container.appendChild(label);
    }
}

// Open a tab
function openTab(evt, tabName) {
    let tabContents = document.getElementsByClassName('tab-content');
    for (let tabContent of tabContents) {
        tabContent.classList.remove('active');
    }

    let tabLinks = document.getElementsByClassName('tab-link');
    for (let tabLink of tabLinks) {
        tabLink.classList.remove('active');
    }

    document.getElementById(tabName).classList.add('active');
    evt.currentTarget.classList.add('active');
}

// Generate Cron Expression
function generateCron() {
    let seconds = getSeconds();
    let minutes = getMinutes();
    let hours = getHours();
    let day = getDay();
    let month = getMonth();
    let week = getWeek();
    let year = getYear();

    let cronExpression = `${seconds} ${minutes} ${hours} ${day} ${month} ${week} ${year}`;
    document.getElementById('cron-expression-output').value = cronExpression;
    updateExecutionTimes();
}

function getSeconds() {
    let seconds = document.querySelector('input[name="seconds"]:checked').value;
    if (seconds === 'range') {
        let start = document.getElementById('seconds-range-start').value;
        let end = document.getElementById('seconds-range-end').value;
        return `${start}-${end}`;
    } else if (seconds === 'interval') {
        let start = document.getElementById('seconds-interval-start').value;
        let interval = document.getElementById('seconds-interval').value;
        return `${start}/${interval}`;
    } else if (seconds === 'specific') {
        let specific = Array.from(document.querySelectorAll('#seconds-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    }
    return seconds;
}

function getMinutes() {
    let minutes = document.querySelector('input[name="minutes"]:checked').value;
    if (minutes === 'range') {
        let start = document.getElementById('minutes-range-start').value;
        let end = document.getElementById('minutes-range-end').value;
        return `${start}-${end}`;
    } else if (minutes === 'interval') {
        let start = document.getElementById('minutes-interval-start').value;
        let interval = document.getElementById('minutes-interval').value;
        return `${start}/${interval}`;
    } else if (minutes === 'specific') {
        let specific = Array.from(document.querySelectorAll('#minutes-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    }
    return minutes;
}

function getHours() {
    let hours = document.querySelector('input[name="hours"]:checked').value;
    if (hours === 'range') {
        let start = document.getElementById('hours-range-start').value;
        let end = document.getElementById('hours-range-end').value;
        return `${start}-${end}`;
    } else if (hours === 'interval') {
        let start = document.getElementById('hours-interval-start').value;
        let interval = document.getElementById('hours-interval').value;
        return `${start}/${interval}`;
    } else if (hours === 'specific') {
        let specific = Array.from(document.querySelectorAll('#hours-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    }
    return hours;
}

function getDay() {
    let day = document.querySelector('input[name="day"]:checked').value;
    if (day === 'range') {
        let start = document.getElementById('day-range-start').value;
        let end = document.getElementById('day-range-end').value;
        return `${start}-${end}`;
    } else if (day === 'interval') {
        let start = document.getElementById('day-interval-start').value;
        let interval = document.getElementById('day-interval').value;
        return `${start}/${interval}`;
    } else if (day === 'specific') {
        let specific = Array.from(document.querySelectorAll('#day-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    } else if (day === 'ignore') {
        return '?';
    } else if (day === 'weekday') {
        let weekday = document.getElementById('day-weekday').value;
        return `${weekday}W`;
    } else if (day === 'last') {
        return 'L';
    } else if (day === 'calendar') {
        let nth = document.getElementById('day-calendar-nth').value;
        return `${nth}C`;
    } return day;
}

function getMonth() {
    let month = document.querySelector('input[name="month"]:checked').value;
    if (month === 'range') {
        let start = document.getElementById('month-range-start').value;
        let end = document.getElementById('month-range-end').value;
        return `${start}-${end}`;
    } else if (month === 'interval') {
        let start = document.getElementById('month-interval-start').value;
        let interval = document.getElementById('month-interval').value;
        return `${start}/${interval}`;
    } else if (month === 'specific') {
        let specific = Array.from(document.querySelectorAll('#month-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    }
    return month;
}

function getWeek() {
    let week = document.querySelector('input[name="week"]:checked').value;
    if (week === 'range') {
        let start = document.getElementById('week-range-start').value;
        let end = document.getElementById('week-range-end').value;
        return `${start}-${end}`;
    } else if (week === 'ignore') {
        return '?';
    } else if (week === 'last') {
        return 'L';
    } else if (week === 'nth') {
        let nthWeek = document.getElementById('week-nth-week').value;
        let nthDay = document.getElementById('week-nth-day').value;
        return `${nthDay}#${nthWeek}`;
    } else if (week === 'specific') {
        let specific = Array.from(document.querySelectorAll('#week-specific input:checked')).map(el => el.value).join(',');
        return specific || '*';
    }
    return week;
}

function getYear() {
    let year = document.querySelector('input[name="year"]:checked').value;
    if (year === 'range') {
        let start = document.getElementById('year-range-start').value;
        let end = document.getElementById('year-range-end').value;
        return `${start}-${end}`;
    }
    return year;
}

// Calculate Execution Times with support for L, W, ?, and C
function calculateExecutionTimes(cronExpression) {
    const fields = cronExpression.split(' ');
    if (fields.length !== 7) {
        document.getElementById("execution-times-list").innerText = "Invalid Cron Expression";
        return;
    }

    const [seconds, minutes, hours, day, month, week, year] = fields;

    // Parse each field
    const secondValues = parseField(seconds, 0, 59);
    const minuteValues = parseField(minutes, 0, 59);
    const hourValues = parseField(hours, 0, 23);
    const monthValues = parseField(month, 1, 12);
    const weekValues = parseWeekField(week, new Date().getFullYear(), new Date().getMonth() + 1); // Parse week field with support for L and ?
    const yearValues = parseYearField(year, 1970, 2099);

    // Get current time
    let currentDate = new Date();

    // Find next 10 execution times
    const executionTimes = [];
    const maxExecutionTimes = 10;
    let executionCount = 0;

    while (executionCount < maxExecutionTimes) {
        // Check if current year is valid
        if (!yearValues.includes(currentDate.getFullYear())) {
            const nextYear = yearValues.find(y => y > currentDate.getFullYear());
            if (nextYear === undefined) break; // No more valid years
            currentDate.setFullYear(nextYear);
            currentDate.setMonth(0, 1); // Reset to January 1st
            currentDate.setHours(0, 0, 0, 0); // Reset time to 00:00:00
            continue;
        }

        // Check if current month is valid
        if (!monthValues.includes(currentDate.getMonth() + 1)) {
            currentDate.setMonth(currentDate.getMonth() + 1, 1); // Move to next month
            currentDate.setHours(0, 0, 0, 0); // Reset time to 00:00:00
            continue;
        }

        // Parse day field with support for L, W, ?, and C
        const dayValues = parseDayField(day, currentDate.getFullYear(), currentDate.getMonth() + 1);

        // Check if current day is valid
        if (!dayValues.includes(currentDate.getDate())) {
            currentDate.setDate(currentDate.getDate() + 1); // Move to next day
            currentDate.setHours(0, 0, 0, 0); // Reset time to 00:00:00
            continue;
        }

        // Check if current week is valid
        if (weekValues.length > 0 && !weekValues.includes(currentDate.getDay() || 7)) {
            currentDate.setDate(currentDate.getDate() + 1); // Move to next day
            currentDate.setHours(0, 0, 0, 0); // Reset time to 00:00:00
            continue;
        }

        // Check if current hour is valid
        if (!hourValues.includes(currentDate.getHours())) {
            currentDate.setHours(currentDate.getHours() + 1, 0, 0, 0); // Move to next hour
            continue;
        }

        // Check if current minute is valid
        if (!minuteValues.includes(currentDate.getMinutes())) {
            currentDate.setMinutes(currentDate.getMinutes() + 1, 0, 0); // Move to next minute
            continue;
        }

        // Check if current second is valid
        if (!secondValues.includes(currentDate.getSeconds())) {
            currentDate.setSeconds(currentDate.getSeconds() + 1, 0); // Move to next second
            continue;
        }

        // If all fields match, add to execution times
        executionTimes.push(currentDate.toLocaleString());
        executionCount++;

        // Move to next second to find the next execution time
        currentDate.setSeconds(currentDate.getSeconds() + 1, 0);
    }

    // Display execution times
    document.getElementById("execution-times-list").innerHTML = executionTimes.join("<br>");
}

// Parse year field
function parseYearField(field, min, max) {
    if (field === "*") {
        return Array.from({ length: max - min + 1 }, (_, i) => i + min);
    } else if (field.includes('-')) {
        const [start, end] = field.split('-').map(Number);
        return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    } else {
        return [Number(field)];
    }
}

// Parse Week field with support for L and ?
function parseWeekField(field, year, month) {
    if (field === "*") {
        return Array.from({ length: 7 }, (_, i) => i); // All days of the week (0-6)
    } else if (field.endsWith("L")) {
        // Last weekday of the month (e.g., 5L for last Friday)
        const day = parseInt(field);
        const lastDay = new Date(year, month, 0).getDate();
        const date = new Date(year, month - 1, lastDay);
        while (date.getDay() !== day) {
            date.setDate(date.getDate() - 1);
        }
        return [date.getDay()];
    } else if (field.includes('#')) {
        const [day, nth] = field.split('#').map(Number);
        const date = new Date(year, month - 1, 1);
        let count = 0;
        while (date.getMonth() === month - 1) {
            if (date.getDay() === day) {
                count++;
                if (count === nth) {
                    return [date.getDay()];
                }
            }
            date.setDate(date.getDate() + 1);
        }
        return [];
    } else if (field === "?") {
        return []; // Ignore week
    } else if (field.includes(',')) {
        return field.split(',').map(Number);
    } else if (field.includes('-')) {
        const [start, end] = field.split('-').map(Number);
        return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    } else if (field.includes('/')) {
        const [start, interval] = field.split('/').map(Number);
        return Array.from({ length: Math.ceil((7 - start + 1) / interval) }, (_, i) => start + i * interval);
    } else {
        return [Number(field)];
    }
}

// Parse Day field with support for L, W, ?, and C
function parseDayField(field, year, month) {
    if (field === "*") {
        return Array.from({ length: 31 }, (_, i) => i + 1); // All days
    } else if (field === "L") {
        // Last day of the month
        const lastDay = new Date(year, month, 0).getDate();
        return [lastDay];
    } else if (field.endsWith("W")) {
        // Nearest weekday (e.g., 15W)
        const day = parseInt(field);
        const date = new Date(year, month - 1, day);
        if (date.getDay() === 0) { // Sunday
            date.setDate(day + 1);
        } else if (date.getDay() === 6) { // Saturday
            date.setDate(day - 1);
        }
        return [date.getDate()];
    } else if (field === "?") {
        return []; // Ignore day
    } else if (field.endsWith("C")) {
        // Calendar day (e.g., 5C)
        const day = parseInt(field);
        const date = new Date(year, month - 1, day);
        while (date.getDay() === 0 || date.getDay() === 6) { // Skip weekends
            date.setDate(date.getDate() + 1);
        }
        return [date.getDate()];
    } else if (field.includes(',')) {
        return field.split(',').map(Number);
    } else if (field.includes('-')) {
        const [start, end] = field.split('-').map(Number);
        return Array.from({ length: end - start + 1 }, (_, i) => start + i);
    } else if (field.includes('/')) {
        const [start, interval] = field.split('/').map(Number);
        return Array.from({ length: Math.ceil((31 - start + 1) / interval) }, (_, i) => start + i * interval);
    } else {
        return [Number(field)];
    }
}

// Parse a cron field (e.g., "*/5" or "1,2,3")
function parseField(field, min, max) {
    if (field === "*") {
        return Array.from({ length: max - min + 1 }, (_, i) => i + min);
    } else if (field.includes(',')) {
        return field.split(',').map(Number);
    } else if (field.includes('-')) {
        const [start, end] = field.split('-').map(Number);
        return Array.from({ length: end - start + 1 }, (_, i) => i + start);
    } else if (field.includes('/')) {
        const [start, interval] = field.split('/').map(Number);
        return Array.from({ length: Math.ceil((max - start + 1) / interval) }, (_, i) => start + i * interval);
    } else {
        return [Number(field)];
    }
}

// Update Execution Times with debounce
let timeout;
function updateExecutionTimes() {
    clearTimeout(timeout);
    timeout = setTimeout(() => {
        const cronExpression = document.getElementById("cron-expression-output").value;
        calculateExecutionTimes(cronExpression);
    }, 300); // Debounce delay of 300ms
}

// Clear other options when one is selected
function clearOtherSecondsOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("seconds-range-start").value = "";
        document.getElementById("seconds-range-end").value = "";
    }
    if (selectedOption !== "interval") {
        document.getElementById("seconds-interval-start").value = "";
        document.getElementById("seconds-interval").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#seconds-specific input').forEach(checkbox => checkbox.checked = false);
    }
}

function clearOtherMinutesOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("minutes-range-start").value = "";
        document.getElementById("minutes-range-end").value = "";
    }
    if (selectedOption !== "interval") {
        document.getElementById("minutes-interval-start").value = "";
        document.getElementById("minutes-interval").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#minutes-specific input').forEach(checkbox => checkbox.checked = false);
    }
}

function clearOtherHoursOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("hours-range-start").value = "";
        document.getElementById("hours-range-end").value = "";
    }
    if (selectedOption !== "interval") {
        document.getElementById("hours-interval-start").value = "";
        document.getElementById("hours-interval").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#hours-specific input').forEach(checkbox => checkbox.checked = false);
    }
}

function clearOtherDayOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("day-range-start").value = "";
        document.getElementById("day-range-end").value = "";
    }
    if (selectedOption !== "interval") {
        document.getElementById("day-interval-start").value = "";
        document.getElementById("day-interval").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#day-specific input').forEach(checkbox => checkbox.checked = false);
    }
    if (selectedOption !== "weekday") {
        document.getElementById("day-weekday").value = "";
    }
}

function clearOtherMonthOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("month-range-start").value = "";
        document.getElementById("month-range-end").value = "";
    }
    if (selectedOption !== "interval") {
        document.getElementById("month-interval-start").value = "";
        document.getElementById("month-interval").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#month-specific input').forEach(checkbox => checkbox.checked = false);
    }
}

function clearOtherWeekOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("week-range-start").value = "";
        document.getElementById("week-range-end").value = "";
    }
    if (selectedOption !== "specific") {
        document.querySelectorAll('#week-specific input').forEach(checkbox => checkbox.checked = false);
    }
}

function clearOtherYearOptions(selectedOption) {
    if (selectedOption !== "range") {
        document.getElementById("year-range-start").value = "";
        document.getElementById("year-range-end").value = "";
    }
}

// Initialize checkboxes with correct ranges
initializeCheckboxes("seconds-specific", 59);
initializeCheckboxes("minutes-specific", 59);
initializeCheckboxes("hours-specific", 23);
initializeCheckboxes("day-specific", 31, "", 1); // Day range 1-31
initializeCheckboxes("month-specific", 12, "Month", 1); // Month range 1-12
initializeCheckboxes("week-specific", 7, "Day", 1); // Week range 1-7

// Open the default tab
document.getElementsByClassName("tab-link")[0].click();

// Theme Toggle
const themeToggle = document.createElement("button");
themeToggle.className = "theme-toggle";
themeToggle.innerText = "Toggle Dark Theme";
document.body.appendChild(themeToggle);

themeToggle.addEventListener("click", () => {
    document.body.classList.toggle("dark-theme");
});